home *** CD-ROM | disk | FTP | other *** search
- unit UPTShellUtils; // Copyright ⌐ 1996-2001 Plasmatech Software Design. All rights reserved.
- {
- Shell Control Pack
- Version 1.6
-
- Implements low-level utilities useful for dealing with shell interfaces and structures.
- Also includes utilities for creating and resolving shortcuts.
-
- History
- ===================================================================================================
- V1.6 2Jul01 Added ShellGetSpecialFolderIconIndex.
- V1.5c 30Mar01 Fixed a memory leak in ShellFindCSIDLFromIdList.
- Fixed DefWndProc call in DeviceChangeHandler to return function result.
- Changed to central acquisition of shell's IMalloc interface to increase stability.
- V1.5b 12Dec00 The hidden DeviceChangeHandler window now calls DefWndProc.
- V1.5a 14May00 No changes.
- V1.5 3Mar00 C++Builder 5 release.
- Added 'noUi' option to TLinkData record.
- Fixed WM_QUERYENDSESSION handling in hidden window used by DeviceChangeHandler.
- V1.4a 15Dec99 Added FlushDriveInfoCache, LockFlushDriveInfoCache, and UnlockFlushDriveInfoCache
- to work around the Windows bug where drive information is cached too vigorously.
- Added TPTDeviceChangeHandler class to manage broadcasting of WM_DEVICECHANGE
- messages to components that wouldn't normally receive the message, but want it
- (like TPTShellTree and TPTShellList).
- V1.4 14Sep99 Added ShellFindCSIDLFromIdList.
- V1.3h 29Mar99 Changed handling of cached IMalloc ptr g_IShm during some shutdown situations
- on NT4.
- Fixed problem with EnsureTrailingCharDB function. It didn't actually work for
- double-byte character sets.
- V1.3g 1Dec98 Added ShellIMalloc.
- V1.3f 12Jul98 Delphi 4 release, no changes.
- V1.3e 22Apr98 Added TPTPidlList object.
- V1.3d 18Apr98 No changes.
- V1.3c 16Mar98 C++Builder 3 support.
- V1.3b 7Feb98 Added GetModuleVersion function and TPTModuleVersion type.
- Added constants, types and variable COMCTL32_VER for determining the version of
- comctl32.dll at run-time.
- Changed ShellGetSystemImageList to support shell link and network share overlay
- fix on WinNT/IE4.
- V1.3a 7Jan98 Added ShellGetIconIndexFromExt.
- Added ShellGetIconIndexFromPath.
- V1.3 28Nov97 No changes.
- V1.2b 12Oct97 No changes.
- V1.2a 5Oct97 No changes.
- V1.2 6Sep97 Added PTClsidFromFileType.
- ShellMemAlloc, ShellMemRealloc and ShellMemFree now used a cached IMalloc interface.
- ShellGetIconIndex method added.
- V1.1a 6Jul97 Removed HWND params for C++Builder support.
- V1.1 26Jun97 Fixed CompareAbsIdLists when Desktop folder used as either or both parameters.
- V1.0c 31May97 No significant changes.
- V1.0b 17May97 Delphi 3 support. Adjusted StrretFree to prevent exceptions under WinNT.
- V1.0a 1May97 Added IsWinNT, IsWin95, HasWin95Shell functions.
- V1.0 21Apr97 Released version 1.0
- }
-
- {$I PTCompVer.inc}
-
- {$RANGECHECKS OFF} {$OVERFLOWCHECKS OFF} {$WRITEABLECONST OFF}
- {$BOOLEVAL OFF} {$EXTENDEDSYNTAX ON} {$TYPEDADDRESS ON}
-
- interface
- uses Windows, SysUtils, ShellApi, Dialogs, Ole2, Messages, Forms, Classes,
- {$IFDEF VCL30PLUS} ComObj, {$ENDIF} // For OleCheck
- UPTShell95;
-
- type TCSIDL = ( csidlDesktop, // $0000
- csidl_None1, // $0001
- csidlPrograms, // $0002
- csidlControls, // $0003
- csidlPrinters, // $0004
- csidlPersonal, // $0005
- csidlFavorites, // $0006
- csidlStartup, // $0007
- csidlRecent, // $0008
- csidlSendTo, // $0009
- csidlBitBucket, // $000A
- csidlStartMenu, // $000B
- csidl_None2, // $000C
- csidl_None3, // $000D
- csidl_None4, // $000E
- csidl_None5, // $000F
- csidlDesktopDirectory, // $0010
- csidlDrives, // $0011
- csidlNetwork, // $0012
- csidlNethood, // $0013
- csidlFonts, // $0014
- csidlTemplates, // $0015
- csidlCommonStartMenu, // $0016
- csidlCommonPrograms, // $0017
- csidlCommonStartup, // $0018
- csidlCommonDesktopDirectory, //$0019
- csidlAppData, // $001a
- csidlPrintHood, // $001b
- csidlNone ); // $001c
-
- {-- General utilities. These are not necessarily shell related but are used by more than one Shell Control Pack unit. -- }
- function IsWin95: Boolean;
- function IsOSR2OrGreater: Boolean; // Returns TRUE if running Win95 OSR2 or higher.
- function IsWinNT: Boolean;
- function IsWin2000: Boolean;
- function HasWin95Shell: Boolean;
-
- type
- TPTModuleVersion = packed record
- case Integer of
- 0: (w1, w2, w3, w4: Word); // Higher number means more significant - w4=major, w3=minor etc.
- 1: (dw1, dw2: Integer);
- {$IFNDEF CBUILDER}
- 2: (asComp: Comp); // Treat as a single 64-bit integer
- {$ENDIF}
- 3: (_1, _2, minor, major: Word);
- 4: (_3, version: Integer);
- end;
- PPTModuleVersion = ^TPTModuleVersion;
- // Unless you are specifically interested in the build version (w2 or w1) then you would normally
- // compare .version members.
-
- function GetModuleVersion( const aModuleName: String; var {out} aVersion: TPTModuleVersion ): Boolean;
-
- {-- Comctl32.dll support --}
- const
- COMCTL32_VER580 = (5 shl 16) or 80; // IE5 version
- COMCTL32_VER472 = (4 shl 16) or 72; // IE4.01 version
- COMCTL32_VER471 = (4 shl 16) or 71; // IE4 version
- COMCTL32_VER470 = (4 shl 16) or 70; // IE3 version
- COMCTL32_VER400 = (4 shl 16) or 00; // Win95 first release version
-
- var
- COMCTL32_VER: TPTModuleVersion;
-
-
- {-- Utilities. There is virtually no performance penalty for using these ShellMem* routines compared
- to calling SHGetMalloc yourself - and you don't have to manage the IMalloc interface. }
- function ShellMemAlloc(size: Cardinal): Pointer;
- procedure ShellMemFree(p: Pointer);
- function ShellMemRealloc(p: Pointer; size: Cardinal): Pointer;
- function ShellIMalloc: IMalloc;
-
- {-- Higher level conversion utils ----}
- function ShellGetFolderFromIdList( p: PItemIdList; var ish: IShellFolder ): HResult;
- function ShellGetIdListFromPath( const path: String; var p: PItemIdList ): HResult;
- function ShellGetPathFromIdList( p: PItemIdList ): String;
- function ShellGetDisplayPathName( aPathName: String ): String; // Returns the properly cased pathname
- function ShellGetSpecialFolderPath( ahwnd: TPTHWND; csidl: TCSIDL ): String;
- function ShellGetSpecialFolderIdList( ahwnd: TPTHWND; csidl: TCSIDL; var idlist: PItemIdList ): HResult;
- function ShellGetIconIndex( absIdList: PItemIdList; uFlags: DWORD ): Integer;
- function ShellGetIconIndexFromPath( const path: String; uFlags: DWORD ): Integer;
- function ShellGetIconIndexFromExt( const ext: String; uFlags: DWORD ): Integer;
- function ShellGetSpecialFolderIconIndex(csidl: TCSIDL; uFlags: DWORD): Integer;
- function ShellFindCSIDLFromIdList( aIdList: PItemIdList ): TCSIDL;
-
- type TPTFriendlyNameFlags = (ptfnNormal, ptfnInFolder, ptfnForParsing);
- function ShellGetFriendlyNameFromIdList( ishf: IShellFolder; pidl: PItemIdList; flags: TPTFriendlyNameFlags ): String;
- {
- If ishf=nil, then pidl is an absolute item id list. A temporary IShellFolder for the desktop will
- be created to get the name.
- flags can be any SHGNO constant.
-
- File system path Display name Notes
- -------------------- ------------------------ ----------------------------------------
- ptfnNormal C:\Windows\File.txt file If not showing extensions
- \\Computer\Share share on computer
- C:\ My Drive (C) Where C has the volume name My Drive
-
- ptfnInFolder C:\Windows\File.txt file
- \\Computer\Share share
- C:\ My Drive (C)
-
- ptfnForParsing C:\Windows\File.txt C:\Windows\File.txt
- \\Computer\Share \\Computer\Share
- C:\ C:\
- }
-
- type TPTShellIconSize = (ptsizSmall, ptsizLarge);
- function ShellGetSystemImageList( aSize: TPTShellIconSize ): THandle;
-
- {-- String utilities -----------------}
- function StrretToString( pidl: PItemIdList; const r: TStrRet ): String;
- procedure StrretFree( const r: TStrRet );
-
- function EnsureTrailingCharDB( const aSource: String; aTrailingChar: Char ): String;
-
- {-- Low-level Pidl Utilities ---------}
- function CopyIdList( ishm: IMalloc; pidl: PItemIdList ): PItemIdList;
- function ConcatIdLists( ishm: IMalloc; aFirst, aSecond: PItemIdList ): PItemIdList;
- function IdListLen( pidl: PItemIdList ): Integer;
- function CompareAbsIdLists( pidl1, pidl2: PItemIdList ): Integer;
- // Compare absolute (relative to desktop) pidls. Returns <0, 0 or >0. If result=MAXINT then function failed.
-
- {The TPTIdListArray class treats an item id list as an array of items. You can easily process each
- element of the pidl.
-
- property Item[ idx: Integer ]: PItemIdList;
- The returned id is allocated from shell memory and returned. You don't have to free it. If you
- want to keep it you should use CopyIdList() to make a copy. Each call to Item invalidates the previous
- return value.
-
- Example:
- procedure DoWork( pa: TPTIdListArray ):
- var p1, p2: PItemIdList;
- begin
- p1 := pa.items[1];
- p2 := pa.items[2]; // !!BUG p1 is now invalid.
- // ... work ...
- end;
-
- You should instead do this:
- procedure DoWork( pa: TPTIdListArray ):
- var p1, p2: PItemIdList;
- begin
- p1:=nil; p2:=nil;
- try
- p1 := CopyIdList(pa.items[1]);
- p2 := CopyIdList(pa.items[2]);
- // ... work ...
- finally
- if Assigned(p1) then ShellMemFree(p1);
- if Assigned(p2) then ShellMemFree(p2);
- end;
- end;
-
- Since you will very rarely be processing more that one item at a time, you should very rarely need to
- go to this trouble.
-
- The GoUp method works in a similar way (it invalidates previous results of GoUp or Item[].
- GoUp(n) removes the last "n" items from the item id list and returns the result. The id list
- being operated on is not affected, hence GoUp() calls on a given TPTIdListArray are NOT cumulative.
- }
- type TPTIdListArray = class(TObject)
- public
- constructor Create( p: PItemIdList );
- destructor Destroy; override;
-
- function GoUp( items: Integer ): PItemIdList;
-
- property ItemCount: Integer read GetCount;
- property Item[idx: Integer]: PItemIdList read GetItem; default;
- end; {TPTIdListArray}
-
-
- type
- TPTPidlList = class(TObject)
- public
- constructor Create;
- destructor Destroy; override;
-
- function Add(const PIDL: PItemIdList): Integer; virtual;
- function AddObject(const PIDL: PItemIdList; aObject: TObject): Integer; virtual;
- procedure Delete(index: Integer);
- procedure Clear;
- function IndexOf(const PIDL: PItemIdList) : Integer;
-
- procedure Insert(Index: Integer; Pidl: PItemIdList);
- procedure InsertObject(Index: Integer; Pidl: PItemIdList; aObject: Pointer);
-
- procedure Sort;
- property PIDLs[index: Integer]: PItemIdList read GetPIDL write SetPIDL; default;
- property Objects[index: Integer]: Pointer read GetObject write SetObject;
- property Sorted: Boolean read FSorted write SetSorted;
- property Malloc: IMalloc read FMalloc write FMalloc;
- property Count: Integer read GetCount;
- property ShellFolder: IShellFolder read FShellFolder write FShellFolder;
-
- property Duplicates: TDuplicates read FDuplicates write FDuplicates;
- property Capacity: Integer read GetCapacity write SetCapacity;
- end;
-
-
-
- {-- Shortcuts Utilities --------------}
- type TLinkDataOption = (ldoUseDesc, ldoUseArgs, ldoUseIcon, ldoUseWorkDir, ldoUseHotKey, ldoUseShowCmd);
- TLinkDataOptions = set of TLinkDataOption;
-
- TLinkData = record
- // Mandatory members
- pathName: String; // Pathname of original object
- options: TLinkDataOptions; // Set of flags indicating optional member usage
-
- // Optional members
- desc: String; // Description of link file (its filename for example)
- args: String; // Command-line arguments
- iconPath: String; // Pathname of file containing the icon
- iconIndex: Integer; // Index of icon in 'iconPath'. -ve values are resource ids (i think?).
- workingDir: String; // Working directory when process starts
- showCmd: Integer; // How to show the initial window
- hotkey: Word; // Hot key for the link
- noUI: Boolean; // Prevent any error or search dialogs from displaying
-
- // Output members - used by ResolveShortcut, not used by CreateShortcut or CreateQuickShortcut
- idList: PItemIdList;
- w32fd: TWin32FindData;
- end; {TLinkData}
-
- function CreateShortcut( const linkPathName: String; const linkData: TLinkData ): HResult;
- function CreateQuickShortcut( const linkPathName, targetPathName: String ): HResult;
-
- function ResolveShortcut( const linkPathName: String; var linkData: TLinkData; afWantIdList: Boolean ): HResult;
-
- //--
- function PTClsidFromFileType( aExtension: String; var aCLSID: TGUID ): Boolean;
-
- //--
- var gFlushDriveInfoSem: Integer;
-
- {$IFNDEF VCL30PLUS}
- procedure OleCheck( code: DWORD );
- {$ENDIF}
-
- procedure FlushDriveInfoCache;
- procedure LockFlushDriveInfoCache;
- procedure UnlockFlushDriveInfoCache;
-
-
- //-- WM_DEVICECHANGE broadcast handler
-
- type
- TPTDeviceChangeEvent = procedure(ASender: TObject; var AMessage: TMessage) of object;
-
- TPTDeviceChangeHandler = class(TObject)
- public
- constructor Create;
- destructor Destroy; override;
- procedure Add(AToNotify: TPTDeviceChangeEvent);
- procedure Remove(AToNotify: TPTDeviceChangeEvent);
- property Active: Boolean read FActive write FActive;
- end;
-
- function PTDeviceChangeHandler: TPTDeviceChangeHandler;
-
- {$IFDEF INTERNAL_DEBUG}
- {__________________________________________________________________________________________________}
- const
- IID_IptDebugMalloc_d2: TGUID = (D1:$6ABABE4E; D2:$641E; D3:$4B86;
- D4:($AF,$D5,$3E,$79,$89,$B0,$A4,$64));
-
- type
- IptDebugMalloc_d2 = class
- {-- IUnknown --}
- function QueryInterface(const iid: Ole2.TIID; var obj): HResult; virtual; stdcall; abstract;
- function AddRef: Longint; virtual; stdcall; abstract;
- function Release: Longint; virtual; stdcall; abstract;
-
- {-- IMalloc --}
- function Alloc(cb: Longint): Pointer; virtual; stdcall; abstract;
- function Realloc(pv: Pointer; cb: Longint): Pointer; virtual; stdcall; abstract;
- procedure IMalloc_Free(pv: Pointer); virtual; stdcall; abstract;
- function GetSize(pv: Pointer): Longint; virtual; stdcall; abstract;
- function DidAlloc(pv: Pointer): Integer; virtual; stdcall; abstract;
- procedure HeapMinimize; virtual; stdcall; abstract;
-
- {-- IptDebugMalloc_d2 --}
- procedure Acquired(p: Pointer); virtual; stdcall; abstract; {Call when you acquire a block that you must free}
- procedure Released(p: Pointer); virtual; stdcall; abstract; {Call this if you hand over responsibility for a block}
- function GetBlockList: TStringList; virtual; stdcall; abstract;
- procedure GetStats(var AAllocCount, AFreeCount, AFreeNotInListCount: Integer); virtual; stdcall; abstract;
- end;
-
-
- TptDebugIMalloc_d2 = class(IptDebugMalloc_d2)
- end;
-
- FWrappedInterface: Ole2.IMalloc;
- FBlocks: TStringList;
-
- procedure AddBlock(p: Pointer);
- procedure RemoveBlock(p: Pointer);
- function PointerToKey(p: Pointer): String;
-
- public
- constructor Create(AWrappedInterface: Ole2.IMalloc);
- destructor Destroy; override;
-
- {-- IUnknown --}
- function QueryInterface(const iid: Ole2.TIID; var obj): HResult; override;
- function AddRef: Longint; override;
- function Release: Longint; override;
-
- {-- IMalloc --}
- function Alloc(cb: Longint): Pointer; override;
- function Realloc(pv: Pointer; cb: Longint): Pointer; override;
- procedure IMalloc_Free(pv: Pointer); override;
- function GetSize(pv: Pointer): Longint; override;
- function DidAlloc(pv: Pointer): Integer; override;
- procedure HeapMinimize; override;
-
- {-- IptDebugMalloc_d2 --}
- procedure Acquired(p: Pointer); override;
- procedure Released(p: Pointer); override;
- function GetBlockList: TStringList; override;
- procedure GetStats(var AAllocCount, AFreeCount, AFreeNotInListCount: Integer); override;
- end;
-
- function GetPtDebugIMalloc(AMalloc: IMalloc): IMalloc;
-
- function GetIMallocAsIptDebugMalloc_d2(AMalloc: IMalloc): IptDebugMalloc_d2;
- {$ENDIF}
-
-
- {__________________________________________________________________________________________________}
- // You can pass these 'verbs' to TPTShellList.DoCommandForAllSelected and TPTShellTree.DoCommandForNode
- // to execute the relevant menu command. These strings are never displayed and are language independent.
-
- // -- These commands are available to most folders --
- const PTSH_CMDS_DELETE = 'delete';
- PTSH_CMDS_PASTE = 'paste';
- PTSH_CMDS_CUT = 'cut';
- PTSH_CMDS_COPY = 'copy';
- PTSH_CMDS_PROPERTIES = 'properties';
- PTSH_CMDS_EXPLORE = 'explore'; // Opens a Windows explorer
- PTSH_CMDS_OPEN = 'open'; // Opens a Windows explorer folder-view
- PTSH_CMDS_FIND = 'find'; // Open the find dialog
- PTSH_CMDS_LINK = 'link'; // Same as 'Create Shortcut' menu item
-
- // -- Commands used by Dialup Networking
- const PTSH_CMDS_DUN_CREATE = 'create'; // Create new connection wizard
- PTSH_CMDS_DUN_CONNECT = 'connect'; // Connect
-
- // -- These are commands that have no 'verb' but have tested to have the same ID under Win95, Win95OSR2, WinNT4 and IE4
- // -- So the id is pretty reliable, but there a no promises!
- // -- The other thing to remember is that the IDs are reused for different types of folders. So make sure you use the
- // -- right command ID with the right kind of folder.
- const PTSH_CMDID_FORMAT = PChar(35); // Only on drive root directory folders
- // Doesn't seem to work
-
- { Substitutes strings of the form %1,%2 etc. into aFmtStr and returns the result. }
- function FormatStrPos( aFmtStr: String; data: array of String ): String;
-
- { Given a command line string 'ins' returns all the parameters, taking into account
- quotes and double-byte characters. }
- procedure ParametizeCmdLineDB( const ins: String; outs: TStrings );
-
- {DBCS enabled TrimRight}
- function TrimRightDB(Str: String): String;
-
- {Copies possible DB char at 'aPos' from 'aSource' and appends to 'aDest', incrementing 'aPos' by 1 or 2.}
- procedure CopyCharDB(var APos: Integer; const ASource: String; var ADest: String);
-
-
- // __ WM_DEVICECHANGE constants ___________________________
- const
- DBT_DEVNODES_CHANGED = $0007;
- DBT_QUERYCHANGECONFIG = $0017;
- DBT_CONFIGCHANGED = $0018;
- DBT_CONFIGCHANGECANCELED = $0019;
- DBT_MONITORCHANGE = $001B;
- DBT_SHELLLOGGEDON = $0020;
- DBT_CONFIGMGAPI32 = $0022;
- DBT_VXDINITCOMPLETE = $0023;
- DBT_VOLLOCKQUERYLOCK = $8041;
- DBT_VOLLOCKLOCKTAKEN = $8042;
- DBT_VOLLOCKLOCKFAILED = $8043;
- DBT_VOLLOCKQUERYUNLOCK = $8044;
- DBT_VOLLOCKLOCKRELEASED = $8045;
- DBT_VOLLOCKUNLOCKFAILED = $8046;
- DBT_NO_DISK_SPACE = $0047;
- DBT_LOW_DISK_SPACE = $0048;
- DBT_DEVICEARRIVAL = $8000; // system detected a new device
- DBT_DEVICEQUERYREMOVE = $8001; // wants to remove, may fail
- DBT_DEVICEQUERYREMOVEFAILED = $8002; // removal aborted
- DBT_DEVICEREMOVEPENDING = $8003; // about to remove, still avail.
- DBT_DEVICEREMOVECOMPLETE = $8004; // device is gone
- DBT_DEVICETYPESPECIFIC = $8005; // type specific event
- DBT_DEVTYP_OEM = $00000000; // oem-defined device type
- DBT_DEVTYP_DEVNODE = $00000001; // devnode number
- DBT_DEVTYP_VOLUME = $00000002; // logical volume
- DBT_DEVTYP_PORT = $00000003; // serial, parallel
- DBT_DEVTYP_NET = $00000004; // network resource
- DBT_DEVTYP_DEVICEINTERFACE = $00000005; // device interface class
- DBT_DEVTYP_HANDLE = $00000006; // file system handle
-
-
- {*********************************************************}
- implementation
-